package com.mes.schedule.manager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.mes.schedule.domain.DeviceTableCombine;
import com.mes.schedule.domain.McDevice;
import com.mes.schedule.domain.MtDevice;
import com.mes.schedule.domain.Resource;
import com.mes.schedule.domain.ResourceConstraint;
import com.mes.schedule.domain.SCalendar;
import com.mes.schedule.domain.SDevice;
import com.mes.schedule.domain.SGroupOperationTask;
import com.mes.schedule.domain.SOperationLink;
import com.mes.schedule.domain.SOperationTask;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.schedule.domain.TaskAssignScheme;
import com.mes.schedule.domain.UcDevice;
import com.mes.schedule.manager.iface.IAssignManager;

@Component("assignManager")
@Transactional
public class AssignManager implements IAssignManager{
	private final static Log log = LogFactory.getLog(AssignManager.class);
	@javax.annotation.Resource
	protected ScheduleOperationTaskManager scheduleOperationTaskManager;
	@javax.annotation.Resource
	public ReadyTaskManager readyTaskManager;
	@javax.annotation.Resource
	protected ScheduleLinkManager scheduleLinkManager;
	@javax.annotation.Resource
	protected ScheduleDeviceManager scheduledeviceManager;
	@javax.annotation.Resource
	protected ScheduleCalendarManager scheduleCalendarManager;

	/**
	 * @param scheduleOperationTaskManager
	 *            the scheduleOperationTaskManager to set
	 */
	public void setScheduleOperationTaskManager(ScheduleOperationTaskManager scheduleOperationTaskManager) {
		this.scheduleOperationTaskManager = scheduleOperationTaskManager;
	}

	/**
	 * 从待调度任务中移除
	 */
	public void removeFromReadyTasks(SOperationTask operationTask) {
		ScheduleScheme scheme = operationTask.getScheme();
		if (scheme.getReadyTaskS() != null && scheme.getReadyTaskS().contains(operationTask)) {
			// 取消任务时后续任务已经在调度集合中，一定要将其清除出去
			this.readyTaskManager.remove(operationTask.getScheme(), operationTask);
		}
	}

	/**
	 * 从待调度任务中移除
	 */
	public void addToReadyTasks(SOperationTask operationTask) {
		ScheduleScheme scheme = operationTask.getScheme();
		this.readyTaskManager.add(scheme, operationTask);
	}

	/*
	 * 获取工序任务的可选资源列表,形成各种组合
	 */
	protected List<TaskAssignScheme> getAlterResourceList(SOperationTask operationTask) {
		log.debug("alterResourceList ,开始！");

		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals("bf6ad62b-8ae3-42ed-8465-1b1ae19480e4")) {
				log.debug(operationTask.toFriendlyString());
			}

		}

		List<TaskAssignScheme> alterResourceList = new ArrayList<TaskAssignScheme>();
		List<SDevice> deviceList = this.getAlterDeviceList(operationTask);
		if (deviceList != null && deviceList.size() > 0) {
			TaskAssignScheme alterResource;
			for (SDevice device : deviceList) {
				SDevice d = device;// .getCalCapacityDevice()==null?device:device.getCalCapacityDevice();

				// 如果日历无能力就将其退出
				if (d.getDeviceUid().equals("538-2")) {
					log.debug("aaaaaaaaaaaa");
				}

				SCalendar calendar = d.getCalendar();
				if (calendar == null)
					continue;

				if (calendar.getSameWithBase() && calendar.getBaseCalendar() != null)
					calendar = (SCalendar) calendar.getBaseCalendar();

				if (calendar.getNoCapacity()) {
					continue;
				}

				if (d instanceof MtDevice) {
					for (DeviceTableCombine cr : ((MtDevice) d).getCombinedResourceList()) {
						alterResource = new TaskAssignScheme(operationTask);
						alterResource.setResource(cr);
						alterResource.setMainDevice(d);
						// alterResource.setPriority(rc.getPriority());
						alterResourceList.add(alterResource);

					}
				} else if (d instanceof McDevice) {
					for (Resource vr : ((McDevice) d).getVirtualDeviceList()) {
						alterResource = new TaskAssignScheme(operationTask);
						alterResource.setResource(vr);

						alterResource.setMainDevice(d);

						// alterResource.setPriority(rc.getPriority());
						alterResourceList.add(alterResource);
					}
				} else {
					alterResource = new TaskAssignScheme(operationTask);
					alterResource.setResource(d);
					// alterResource.setPriority(rc.getPriority());
					alterResourceList.add(alterResource);

				}
			}

			// 这里排序是什么意思啊？无意义
			// todo
			// if (alterResourceList.size() > 1) {
			// Collections.sort(alterResourceList, new Comparator<Object>() {
			// public int compare(Object o1, Object o2) {
			// AlterResource constraint1 = (AlterResource) o1;
			// AlterResource constraint2 = (AlterResource) o2;
			// int i = 0;
			// if (constraint1.getPriority() > constraint2.getPriority()) {
			// i = 1;
			// }
			// return i;
			// }
			// });
			// } else
		} else {
			log.warn("adadad4235235345");
		}
		if (alterResourceList.size() == 0) {
			log.warn("严重警告，任务" + operationTask + "没有找到任何 可选资源！");

		}

		log.debug("alterResourceList,结束！");
		return alterResourceList;
	}

	/*
	 * 获取工序任务的可选资源列表 在静态的设备基础上，扣除很多动态的禁忌设备
	 */
	public List<SDevice> getAlterDeviceList(SOperationTask operationTask) {
		log.debug("alterResourceList,开始！");

		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals("9cf3469e-883e-4798-873f-2812bbba2d35")) {
				log.debug(operationTask.toFriendlyString());

			}

		}
		List<SDevice> alterDeviceList = new ArrayList<SDevice>();

		ScheduleScheme scheduleScheme = operationTask.getScheme();

		/**
		 * 主要用于两阶段算法
		 */
		if (operationTask.getCalFixedDeviceUid() != null) {
			SDevice calDevice = scheduleScheme.getDeviceMap().get(operationTask.getCalFixedDeviceUid());
			if (calDevice != null) {
				alterDeviceList.add(calDevice);
				return alterDeviceList;
			}

		}

		if (operationTask.getAlterResourceMap() == null || operationTask.getAlterResourceMap().isEmpty())
			this.scheduleOperationTaskManager.calcAlterResourceList(operationTask);
		for (ResourceConstraint r : operationTask.getAlterResourceMap().values()) {

			SDevice d = r.getDevice();
			if (d.getCalendar() == null || d.getCalendar().getNoCapacity()) {
				continue;
			}

			// 因为前面calFixedDevice不为空时，已经return
			// 所以可以在此进行判断
			if (d.getCalForbiddenAppendAssign())
				continue;

			alterDeviceList.add(r.getDevice());
		}

		if (alterDeviceList.size() == 0) {
			log.warn("严重警告，任务" + operationTask + "没有找到任何可选设备!");
			return alterDeviceList;
		} else if (alterDeviceList.size() == 1) {
			return alterDeviceList;
		}

		try {
			Set<SDevice> deletedDeviceList = new HashSet<SDevice>();

			// 前道工序和流水工序的限制
			// 流水工序不能在同一设备上做
			if (operationTask.getPredLinkSet() != null) {

				for (SOperationLink sl : (operationTask.getPredLinkSet())) {
					SOperationTask predTask = sl.getPredOperationTask();
					// 判断设备是否相同
					if (predTask.getAssignState().equals(SOperationTask.ASSNSTATE_SUCCESS) && sl.getMoveType() != null
							&& (sl.getMoveType().equals(SOperationLink.MOVETYPE_FLOW)
									|| sl.getMoveType().equals(SOperationLink.MOVETYPE_FLOWSEQUENCE))) {
						log.debug("移除平行与流水加工时前置工序任务" + predTask + "的设备：" + predTask.getDevice());

						for (SDevice rc : alterDeviceList) {
							if (predTask.getDeviceUid().equals(rc.getDeviceUid())) {
								deletedDeviceList.add(rc);
								break;

							}
						}

					}

				}

			}

			// 前道工序和流水工序的限制
			// 流水工序不能在同一设备上做
			if (operationTask.getCalDeviceSeq() == null) {
				for (SDevice d : alterDeviceList) {
					if (d.getInterruptDeviceQueue().size() > 0) {
						for (SOperationTask iTask : d.getInterruptDeviceQueue()) {
							// 设置队列中的任务未成功的条件有些冗余，主要是为了避免isPredTask的效率问题
							if (iTask.getAssignState() != SOperationTask.ASSNSTATE_SUCCESS) {
								deletedDeviceList.add(d);
								break;
							}
						}
					}
				}
			}
			for (SDevice d : deletedDeviceList) {
				if (alterDeviceList.size() > 1)// 大于1个再移除
					alterDeviceList.remove(d);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		log.debug("alterResourceList,设备！");
		return alterDeviceList;
	}

	/*
	 * 1=标识成功 -1=继续等待前道工序 -2=已经失败，无需调度
	 */

	protected int beforeAssign(SOperationTask operationTask) throws Exception {
		log.debug("进入前置任务判断beforeAssign：" + operationTask);
		int iResult = 1;
		// 前道工序和流水工序的限制
		Set<SOperationLink> predLinkSet = operationTask.getPredLinkSet();
		if (predLinkSet != null && predLinkSet.size() > 0) {

			for (SOperationLink sl : (operationTask.getPredLinkSet())) {
				SOperationTask predTask = sl.getPredOperationTask();
				// 前道工序没有排的立即排产
				// todo
				// 可能应该逆序排产

				if (predTask.getAssignState() == SOperationTask.ASSNSTATE_WAITING) {
					log.debug("前置关系引起排产，" + predTask);
					this.assignTask(predTask);
				}

				if (predTask.getAssignState() == SOperationTask.ASSNSTATE_STARTED) {

					if (scheduleLinkManager.isPredTask(operationTask, predTask))// 是否双向关联，忽略此限制
					{
						log.warn("警告:系统出现环路链接设置，请仔细检查！任务1为：" + predTask + ",任务2为：" + operationTask);
						// 环路链接继续排
					} else
						return -1;// 要求你继续等待前置任务
				} else if (predTask.getAssignState() == SOperationTask.ASSNSTATE_FAILURE) {
					log.warn("警告，前序任务" + predTask + "已经调度失败");
					return -2;
				}

			}

		}
		return 1;

	}

	/*
	 * 设备序列处理
	 */
	private boolean deviceSeqPro(SOperationTask operationTask, SDevice scheduleDevice) throws Exception {
		// if(operationTask.getDevice().getDeviceName().equals("钳工台"))
		// {
		// log.debug(operationTask);
		//
		// }
		// 流水工序不能在同一设备上做

		// && operationTask.getDeviceSeq() != null
		// && operationTask.getDeviceSeq() > 0

		TreeSet<SOperationTask> interruptDeviceQueue = scheduleDevice.getInterruptDeviceQueue();

		if (interruptDeviceQueue != null && interruptDeviceQueue.size() > 0) {
			// if (log.isDebugEnabled()) {
			// for (SOperationTask queueTask : interruptDeviceQueue) {
			// log.debug("设备队列引起的提前分派,排序号为：" + queueTask.getDeviceSeq()
			// + ", " + queueTask);
			//
			// }
			// }

			for (SOperationTask queueTask : interruptDeviceQueue) {
				if (queueTask.equals(operationTask))
					break;
				if (queueTask.getAssignState() == SOperationTask.ASSNSTATE_WAITING) {

					// 判断是否是前置工序，前置工序优先
					if (!(scheduleLinkManager.isPredTask(operationTask, queueTask))) {
						log.debug("设备队列号为：" + queueTask.getDeviceSeq() + "，任务为：" + queueTask);
						this.assignTask(queueTask);

					}
				}
				if (queueTask.getAssignState() != SOperationTask.ASSNSTATE_SUCCESS)
					return false;// 不成功不让它先调度设备队列之后的任务
			}

		}

		return true;

	}

	public void afterAssign(SOperationTask operationTask) throws Exception {
		// TODO Auto-generated method stub
		log.debug("开始进行任务分配后处理，" + operationTask);
		ScheduleScheme scheme = operationTask.getScheme();

		// readyTaskManager.remove(scheme, operationTask);//外面已经自动清除

		// //不论调度是否成功
		// if(scheme.isAllowDeviceQueueInterrupt()&&operationTask.getDeviceSeq()!=null)
		// {
		// Device device=operationTask.getDevice();
		// if(device!=null)
		// device.getInterruptDeviceQueue().remove(operationTask);
		// }

		if (operationTask.getAssignState() == SOperationTask.ASSNSTATE_SUCCESS) {

			if (scheme.isAllowDeviceQueueInterrupt() && operationTask.getCalDeviceSeq() != null
					&& operationTask.getCalDeviceSeq() > 0 && operationTask.getDevice() != null) {

				TreeSet<SOperationTask> interruptDeviceQueue = operationTask.getDevice().getInterruptDeviceQueue();

				if (interruptDeviceQueue != null && interruptDeviceQueue.size() > 0) {

					if (operationTask.getCalDeviceSeq() > 0) {
						// 设备序列任务优先，产生对其它任务最早开始时间的约束
						int planStartSegement = scheme.calSegementFromDate(operationTask.getPlanStart());
						if (planStartSegement > operationTask.getDevice().getDeviceSeqEarlyStartSegement())
							operationTask.getDevice().setDeviceSeqEarlyStartSegement(planStartSegement);
					}
					for (SOperationTask queueTask : interruptDeviceQueue) {
						// log
						// .info("设备队列引起的提前分派 后续影响,排序号为："
						// + queueTask.getDeviceSeq() + ", "
						// + queueTask);
						// 同顺序号的不产生时间限制，表示可以并行，非>=
						if ((queueTask.getAssignState() == SOperationTask.ASSNSTATE_WAITING
								|| queueTask.getAssignState() == SOperationTask.ASSNSTATE_STARTED)
								&& queueTask.getCalDeviceSeq() > operationTask.getCalDeviceSeq()) {
							if (queueTask.getControlEarlyStart().before(operationTask.getPlanStart())) {
								queueTask.setControlEarlyStart(operationTask.getPlanStart());
								log.debug("设备队列引起柔性最早开始时间限制，排序号为：" + queueTask.getCalDeviceSeq() + ",任务为： " + queueTask
										+ ",最早开始为：" + operationTask.getPlanStart());
							}
						}
					}

				}
			}

			Set<SOperationLink> succLinkSet = operationTask.getSuccLinkSet();
			if (succLinkSet != null && succLinkSet.size() > 0) {
				for (SOperationLink succLink : succLinkSet) {
					SOperationTask succTask = succLink.getSuccOperationTask();

					if (succTask.getGroupTask() != null)
						succTask = succTask.getGroupTask();
					// 处理完了之后再计算其最早开始时间
					// 添加之前，先计算松弛和优先级
					scheduleOperationTaskManager.calcControlEarlyStart(succTask);
					scheduleOperationTaskManager.calcControlEarlyFinish(succTask);

					if (succLink.getMoveType() == SOperationLink.MOVETYPE_FLOW
							|| succLink.getMoveType() == SOperationLink.MOVETYPE_FLOWSEQUENCE) {
						// 平行平顺提前抢占资源
						this.assignTask(succTask);
					} else {
						if (succTask.getAssignState() == SOperationTask.ASSNSTATE_WAITING
								&& scheduleOperationTaskManager.isReady(succTask)) {
							readyTaskManager.add(scheme, succTask);
						}
					}
				}
			}
		}

		else {
			// 不用在这里清除,beforeassign对这里有转么处理
			// operationTask.setPlanStart(null);// 只清除结束，万一在开始时间上有锁定标识
			// operationTask.setPlanFinish(null);
			operationTask.setAssignState(SOperationTask.ASSNSTATE_FAILURE);
			log.warn(operationTask + " 任务调度失败！");
		}

		// 对组任务的处理
		if (operationTask instanceof SGroupOperationTask) {
			SGroupOperationTask sg = (SGroupOperationTask) operationTask;
			List<SOperationTask> members = sg.getMemberTasks();
			if (members != null && members.size() > 0) {
				for (SOperationTask mo : sg.getMemberTasks()) {
					mo.setAssignState(sg.getAssignState());
					mo.setPlanStart(sg.getPlanStart());
					mo.setPlanFinish(sg.getPlanFinish());
				}
			}
		}
	}

	protected int operationDeviceSeqPro(SOperationTask operationTask) throws Exception {
		log.debug("开始进行设备队列处理:" + operationTask);

		// 在其所有可选资源上进行设备队列处理
		// 原来放在beforeassign中是存在问题的，这样会导致必须是固定设备才会保持队列
		//
		// 这一段代码属于额外的处理，应该移出本函数，现在受制于getAlterResourceList
		List<TaskAssignScheme> alterResourceList = getAlterResourceList(operationTask);
		Set<SDevice> tmpDeviceSet = new HashSet<SDevice>();
		// 过滤掉重复的
		for (TaskAssignScheme alterResource : alterResourceList) {
			// 在预分派之前先进行设备队列处理
			SDevice device = alterResource.getMainDevice();
			if (!device.getVirtual())
				tmpDeviceSet.add(device);
		}
		if (tmpDeviceSet.size() == 1) {
			// 一台设备严格按照序列
			if (!deviceSeqPro(operationTask, (SDevice) tmpDeviceSet.iterator().next()))
				return -1;
		} else {
			// 有多台可选设备的暂时不能严格按照顺序
			for (SDevice device : tmpDeviceSet) {
				deviceSeqPro(operationTask, device);
			}
		}
		tmpDeviceSet = null;
		return 1;
	}

	/**
	 * 
	 * 分派任务， 应该是取最早完成
	 * 
	 * @param operTask
	 * 
	 * @return
	 */
	public void assignTask(SOperationTask operationTask) throws Exception {

		try {
			if (operationTask.getAssignState() == SOperationTask.ASSNSTATE_WAITING)
				operationTask.setAssignState(SOperationTask.ASSNSTATE_STARTED);
			else
				return;// 防止了出现回路

			if (operationTask.isFinished())
				return;

			if (operationTask.getGroupTask() != null) {
				log.debug("开始进入成组任务调度:" + operationTask.getGroupTask());
				assignTask(operationTask.getGroupTask());
				return;
			}

			if (log.isDebugEnabled()) {
				if (operationTask.getTaskUid().equals("a9aa5562-a9f9-4402-b950-9a478ba44e14")) {
					log.debug(operationTask);
				}
				if (operationTask.getDrawingId().equals("p229") && operationTask.getBatchNum().equals("2P1106")
						&& operationTask.getOperationIdDesc().equals("75")) {
					log.debug(operationTask);
				}
			}
			ScheduleScheme scheme = operationTask.getScheme();

			if (scheme.isAllowDeviceQueueInterrupt()) {
				int iSeqProResult = operationDeviceSeqPro(operationTask);
				if (iSeqProResult == -1)// 重新让其进入待调度任务队列
				{
					operationTask.setAssignState(SOperationTask.ASSNSTATE_WAITING);
					readyTaskManager.remove(scheme, operationTask);
					return;
				}
			}

			int iPreAssnResult = beforeAssign(operationTask);
			if (iPreAssnResult == -1)// 重新让其进入待调度任务队列
			{

				operationTask.setAssignState(SOperationTask.ASSNSTATE_WAITING);
				readyTaskManager.remove(scheme, operationTask);
				return;

			}

			else if (iPreAssnResult == -2)// 失败
			{

				// 将本任务也设置成失败
				operationTask.setAssignState(SOperationTask.ASSNSTATE_FAILURE);
				readyTaskManager.remove(operationTask.getScheme(), operationTask);
				return;
			}
			// 只有前置任务都分配成功，才允许进行调度
			this.doAssignTask(operationTask);

			// 进入分配后的处理
			this.afterAssign(operationTask);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * 对所有资源进行预分派
	 */
	public void preAssnTask(List<TaskAssignScheme> alterResourceList) throws Exception {
		for (TaskAssignScheme alterResource : alterResourceList) {

			// todo
			// 可选资源的工时可能会不同
			try {
				preAssnTask(alterResource);
			} catch (Exception e) {
				log.error(e.getMessage());

			}

		}
	}

	/**
	 * 对工序任务的多个结果进行投标选择
	 * 
	 * @param operationTask
	 * @param taskAssignSchmeList
	 * @return
	 */
	protected TaskAssignScheme selectTaskAssignScheme(SOperationTask operationTask,
			List<TaskAssignScheme> taskAssignSchmeList) {
		TaskAssignScheme selectedTaskAssignScheme = null;
		List<TaskAssignScheme> successTaskAssignSchemeList = new ArrayList<TaskAssignScheme>();

		for (TaskAssignScheme alterResource : taskAssignSchmeList) {
			// 必须分配成功
			if (alterResource.getPreAssignResult() != null && alterResource.getPreAssignResult().isAssnSuccess()) {
				successTaskAssignSchemeList.add(alterResource);
			}
		}

		if (successTaskAssignSchemeList.size() > 1)
			selectedTaskAssignScheme = assnEvaluation(operationTask, successTaskAssignSchemeList);
		else if (successTaskAssignSchemeList.size() == 1)
			selectedTaskAssignScheme = successTaskAssignSchemeList.get(0);
		else {
			log.warn("任务没有调度成功，没有任何设备 被选中," + operationTask.toFriendlyString());
		}
		return selectedTaskAssignScheme;
	}

	// todo
	// 对任务进行招标处理，确定最终选择资源
	protected List<TaskAssignScheme> callForBidScheme(SOperationTask operationTask) throws Exception {
		// List<TaskAssignScheme> taskAssignSchmeList=new
		// ArrayList<TaskAssignScheme>();
		// 选取设备
		List<TaskAssignScheme> taskAssignSchmeList = this.getAlterResourceList(operationTask);
		// 预分派
		preAssnTask(taskAssignSchmeList);

		return taskAssignSchmeList;
	}

	// todo
	// 对任务进行招标处理，确定最终选择资源
	protected TaskAssignScheme tenderTask(SOperationTask operationTask) throws Exception {
		// List<TaskAssignScheme> taskAssignSchmeList=new
		// ArrayList<TaskAssignScheme>();

		List<TaskAssignScheme> taskAssignSchmeList = this.callForBidScheme(operationTask);
		/**
		 * 
		 * 对工序任务的多个结果进行投标选择
		 */
		TaskAssignScheme selectedTaskAssignScheme = this.selectTaskAssignScheme(operationTask, taskAssignSchmeList);

		return selectedTaskAssignScheme;

	}

	// todo
	// lqm,如何对无线能力设备忽略此评估
	protected TaskAssignScheme assnEvaluation(SOperationTask operationTask, List<TaskAssignScheme> alterResourceList) {
		ScheduleScheme scheme = operationTask.getScheme();

		int maxFinishSegement = -Integer.MAX_VALUE;
		int minFinishSegement = Integer.MAX_VALUE;

		int maxNotRobustCount = -Integer.MAX_VALUE;
		int minNotRobustCount = Integer.MAX_VALUE;

		int maxUseCount = -Integer.MAX_VALUE;
		int minUseCount = Integer.MAX_VALUE;

		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals("3552125")) {
				log.debug("aaa");
			}
		}

		int stdNeedSegment = (int) Math.round(operationTask.getEstiTaskWork() / scheme.getScheduleInterval());
		if (stdNeedSegment == 0) {
			stdNeedSegment = 1;
		}

		// 缺省分数
		for (TaskAssignScheme alterResource : alterResourceList) {
			log.debug("开始评估" + alterResource.getMainDevice() + "的分派结果！");
			float score = 0f;

			int assnPriority = this.scheduleOperationTaskManager.calAssnPriority(operationTask,
					alterResource.getMainDevice().getDeviceUid());

			switch ((int) (assnPriority)) {
			case 1: {
				score = 200;// 满分100分
				break;
			}
			case 2: {
				score = 100;// 扣除10天，保证必须安排,设置成100分，保证尽可能的权威性
				break;
			}
			case 3: {
				score = 60;// 一般情况
				break;
			}
			case 4: {
				score = 40;// 增加10天，保证尽可能不排
				break;
			}
			case 5: {
				score = -200;// 保证必须不安排,也不会进入此case
				break;
			}
			default:
				score = 60;
				break;

			}

			log.debug(alterResource.getMainDevice() + "基准评价分为：" + score);
			PreAssignResult preAssignResult = alterResource.getPreAssignResult();

			// 设备转换代价
			if (preAssignResult.getNeedSegment() < stdNeedSegment)
				score += 50;

			// 计算延迟产生的影响
			int finishSegement = preAssignResult.getPlanFinishSegement();

			if (finishSegement > maxFinishSegement)
				maxFinishSegement = finishSegement;
			if (finishSegement < minFinishSegement)
				minFinishSegement = finishSegement;

			int notRobustCount = alterResource.getMainDevice().getNotRobustCount();
			if (notRobustCount > maxNotRobustCount)
				maxNotRobustCount = notRobustCount;
			if (notRobustCount < minNotRobustCount)
				minNotRobustCount = notRobustCount;

			int useCount = alterResource.getMainDevice().getTotalUseCount();
			if (useCount > maxUseCount)
				maxUseCount = useCount;
			if (useCount < minUseCount)
				minUseCount = useCount;
			// lqm todo
			// 應該y
			// 如果松弛率很大而且前道工序在此加工，加分数40
			// 尽量在同一台设备上做，减少周转
			// log.debug("任务松弛系数为："+operationTask.getSlackFactor());
			// operationTask.getSlackFactor() > 0
			// &&
			if (operationTask.getPredLinkSet() != null) {

				for (SOperationLink sl : (operationTask.getPredLinkSet())) {
					SOperationTask predTask = sl.getPredOperationTask();
					// 判断设备是否相同
					log.debug("前置工序任务" + predTask + "的设备：" + predTask.getDevice());
					if (predTask.getAssignState() == SOperationTask.ASSNSTATE_SUCCESS && predTask.getDeviceUid() != null
							&& predTask.getDeviceUid().equals(alterResource.getMainDevice().getDeviceUid())) {
						// 判断相差是否很远
						// todo 在两小时之内，应该作为一个全局规则
						// 没有考虑一种情况，刚好跨班
						// 两道工序之内的
						// int preFinishSegement = scheme
						// .calSegementFromDate(predTask.getPlanFinish());
						// if (preAssignResult.getPlanFinishSegement()
						// - preFinishSegement < 240 / (scheme
						// .getScheduleInterval())) {
						score += 35;
						log.debug("设备" + alterResource.getMainDevice().getDeviceName() + ",同批零件物流周转加分：+35");
					}

					break;
				}

			}
			// 有要取消的任務扣分
			if (preAssignResult.getNeedCancelAssignTasks().size() > 0)
				score -= preAssignResult.getNeedCancelAssignTasks().size();

			alterResource.setScore(score);

		}

		// 对延迟时间段进行打分,延迟时间给30分的基准
		for (TaskAssignScheme alterResource : alterResourceList) {
			float finishScore = 30;
			if (maxFinishSegement - minFinishSegement > 0) {
				finishScore = (maxFinishSegement - alterResource.getPreAssignResult().getPlanFinishSegement())
						/ (maxFinishSegement - minFinishSegement) * finishScore;
			}
			log.debug("设备" + alterResource.getMainDevice().getDeviceName() + "交货期评分为" + finishScore);
			alterResource.setScore(alterResource.getScore() + finishScore);
		}

		// 对均衡进行打分
		for (TaskAssignScheme alterResource : alterResourceList) {

			float finishScore = 0;
			if (maxUseCount - minUseCount > 0) {
				finishScore = (maxUseCount - alterResource.getMainDevice().getTotalUseCount())
						/ (maxUseCount - minUseCount) * 5f;
			}
			log.debug("设备" + alterResource.getMainDevice().getDeviceName() + "均衡度分为" + finishScore);
			alterResource.setScore(alterResource.getScore() + finishScore);
		}
		// // 对新品成熟度进行考虑
		// if (operationTask.getMaturity() != 1) {
		// for (TaskAssignScheme alterResource : alterResourceList) {
		//
		// float finishScore = 0;
		// if (maxNotRobustCount - minNotRobustCount > 0) {
		// finishScore = (alterResource.getMainDevice()
		// .getNotRobustCount() - minNotRobustCount)
		// / (maxNotRobustCount - minNotRobustCount) * (-5);
		// }
		// log.debug("设备" + alterResource.getMainDevice().getDeviceName()
		// + " 新品搭配扣分为" + finishScore);
		// alterResource.setScore(alterResource.getScore() + finishScore);
		// }
		// }

		// 对预期将来的任务进行考虑

		if (log.isDebugEnabled()) {
			for (TaskAssignScheme alterResource : alterResourceList) {
				log.debug(alterResource.getMainDevice().getDeviceName() + "评估分数：" + alterResource.getScore());
			}

		}
		// 排序，取得分最高设备
		TaskAssignScheme selectedResource = Collections.max(alterResourceList);
		// Collections.sort(alterResourceList, new Comparator<Object>() {
		// public int compare(Object o1, Object o2) {
		// AlterResource r1 = (AlterResource) o1;
		// AlterResource r2 = (AlterResource) o2;
		// int i = 1;
		// if (r1.getScore() > r2.getScore()) {
		// i = -1;
		// }
		// return i;
		// }
		// });
		log.debug(
				"最终选择设备:" + selectedResource.getMainDevice().getDeviceName() + "评估分数为：" + selectedResource.getScore());
		return selectedResource;
	}

	// public int preAssTask(SOperationTask operationTask,MtDevice mtDevice)
	// {
	// for(CombinedResource cr:(mtDevice.getCombinedResourceList()))
	// ｛
	//
	// ｝
	// }

	/**
	 * 取得在任务分配时情况下的资源日历
	 */
	protected int getSegementAssnCalendar(SOperationTask operationTask, Resource resource, int i) {
		SCalendar taskCalendar = operationTask.getCalendar();

		if (taskCalendar != null)
			return this.scheduleCalendarManager.getSegementCalendar(taskCalendar, i);
		else {
			return this.scheduledeviceManager.getSegementCalendar(resource, i);// 按照任务日历,忽略资源日历
		}

	}

	/**
	 * !
	 * 
	 * @param operTask
	 * @param device
	 * @return
	 * @throws Exception
	 */

	public void preAssnTask(TaskAssignScheme alterResource) throws Exception {

		Resource resource = alterResource.getResource();

		if (resource.getResUid().equals("4048879")) {
			log.debug("aaaaaa");
		}

		SOperationTask operationTask = alterResource.getOperationTask();
		if (resource == null) {
			throw new Exception("预分派任务中设备为空！" + operationTask);
		}
		if (log.isDebugEnabled()) {
			if ("cooperation".equals(resource.getResUid())) {
				log.debug("设备为协作");
			}
			if (operationTask.getDrawingId().equals("P18224") && operationTask.getBatchNum().equals("2S1201-分2")
					&& operationTask.getOperationIdDesc().equals("60")) {
				log.debug(operationTask);
			}
			if (operationTask.getTaskUid().equals("dd82f6b4-f3ad-4d9c-b94c-b4f77b03675a")) {
				log.debug(operationTask);
			}

		}

		log.debug("preAssTask预分派开始： " + resource + "开始预分派任务" + operationTask);

		ScheduleScheme scheduleScheme = operationTask.getScheme();
		int interval = scheduleScheme.getScheduleInterval();
		PreAssignResult result = new PreAssignResult();
		int earlyStartSegment = 0;
		// 下面这段话重复执行多遍，应该移到assign方法中
		// todo
		Date controlEarlyStart = operationTask.getControlEarlyStart();

		earlyStartSegment = scheduleScheme.calSegementFromDate(controlEarlyStart);
		if (earlyStartSegment < 0) {
			earlyStartSegment = 0;
		}
		// 只对没有设置序列的程序起作用
		if (scheduleScheme.isAllowDeviceQueueInterrupt()
				&& (operationTask.getCalDeviceSeq() == null || operationTask.getCalDeviceSeq().equals(0))
				&& alterResource.getMainDevice().getDeviceSeqEarlyStartSegement() > earlyStartSegment) {
			earlyStartSegment = alterResource.getMainDevice().getDeviceSeqEarlyStartSegement();
		}

		int needSegment = (int) Math.round(operationTask.getEstiTaskWork() / interval);
		if (needSegment == 0) {
			needSegment = 1;
		}

		// result.setLagSegement(sig-earlyStartSegment);//应该扣除最开始的 日历本身的空闲时间吗？？？
		Date controlEarlyFinish = operationTask.getControlEarlyFinish();
		int controlEarlyFinishSegement = scheduleScheme.calSegementFromDate(controlEarlyFinish);
		// if (controlEarlyFinish != null) {
		//
		// if (result.getPlanFinishSegement() < controlEarlyFinishSegement) {
		// log.debug("最早完成时间限定生效:" + controlEarlyFinishSegement);
		// result.setPlanFinishSegement(controlEarlyFinishSegement);
		//
		// }
		// }

		int startSegment = earlyStartSegment;

		int freeSegment = 0;

		List<Integer> useSegementList = new ArrayList<Integer>();

		// 允许自动加班
		boolean allowOverTime = (scheduleScheme.getAllowAutoOvertime() != null && scheduleScheme.getAllowAutoOvertime()
				&& scheduleScheme.getOvertimeSlack() != null
				&& operationTask.getSlackFactor() <= scheduleScheme.getOvertimeSlack()) ? true : false;

		for (int i = earlyStartSegment; i < scheduleScheme.getTotalSegement(); i++) {
			int segementCalendar = getSegementAssnCalendar(operationTask, resource, i);// 按照任务日历,忽略资源日历
			int segementUse = resource.getSegementUse(i);

			// allowovertime应该与calendar_overtime挂钩
			if ((segementCalendar == SCalendar.CALENDAR_NOMAL || segementCalendar == SCalendar.CALENDAR_OVERTIME
					|| allowOverTime) && segementUse == SDevice.DEVICE_IDLE) {

				if (freeSegment == 0) {
					useSegementList.clear();
					startSegment = i;
					result.setInterruptCount(0);

				}
				freeSegment++;
				useSegementList.add(i);// 加入第i个时间段
				if (freeSegment >= needSegment && i >= controlEarlyFinishSegement) {
					result.setAssnSuccess(true);
					result.setPlanFinishSegement(i);
					result.setPlanStartSegement(startSegment);
					break;
				}

			} else {
				// if (operationTask.getLocked() == 0) {// 非锁定任务才能改开始时间//todo
				// why
				// 不能加工,如果时间段被占用
				if (segementUse == SDevice.DEVICE_PROCESS || segementUse == SDevice.DEVICE_SETUP) {
					// 如果剩下的超过允许的最大重叠系数，则认为可以完成
					// 注意一定要用小数1.0
					double overlap = (needSegment - freeSegment) * 1.0 / needSegment;// todo
					// log.debug("剩余百分比为"+overlap);

					if (overlap <= scheduleScheme.getMaxOverlap() && i >= controlEarlyFinishSegement) {
						// todo
						// 这种完成应该允许扣分

						log.debug("本任务打折满足，共需要:" + needSegment + ",已分配：" + freeSegment + ",剩余工时百分比为" + overlap);
						result.setAssnSuccess(true);
						result.setPlanFinishSegement(i);
						result.setPlanStartSegement(startSegment);
						break;
					}
					// 如果任务允许分隔，否则不允许插孔
					// 多工作台设备允许中断
					// 缺省为有二小时空档就继续做，应该参数化
					// todo
					// 应该是一个比例

					if (operationTask.getCanSplit() && resource instanceof DeviceTableCombine
							&& freeSegment >= 120 / scheduleScheme.getScheduleInterval())// 如果是一个多工作台设备
					{
						// //todo
						// //这里的120分钟 应该参数化
						// continue;
						result.setInterruptCount(result.getInterruptCount() + 1);
					} else
						freeSegment = 0;
				}

				// if ((segementUse == Device.DEVICE_BREAKDOWN ||
				// segementCalendar == Device.DEVICE_CLOSINGTIME)
				// && freeSegment == 0) {
				// startSegment = i + 1;
				// }
			}

			// }
		}

		result.setUseSegementList(useSegementList);
		useSegementList = null;
		log.debug("preAssTask预分派完成，设备为： " + resource + "任务为：" + operationTask + "结果为：" + result);
		alterResource.setPreAssignResult(result);

	}

	/**
	 * 分派任务到设备上
	 * 
	 * @param operTask
	 * @param device
	 * @param es
	 */
	public boolean assignTaskToResource(SOperationTask operationTask, TaskAssignScheme taskAssignScheme)
			throws Exception {
		ScheduleScheme scheme = operationTask.getScheme();
		Resource resource = taskAssignScheme.getResource();

		PreAssignResult preAssignResult = taskAssignScheme.getPreAssignResult();

		if (operationTask.getTaskUid().equals("012db128-f3ce-4dad-97ae-aa5c9d4b5c1a")) {
			log.debug(operationTask);
		}

		// 将资源信息临时存储，可能是组合资源或者虚拟资源
		operationTask.setAssignedResource(resource);

		int startSegment = preAssignResult.getPlanStartSegement();
		int endSegment = preAssignResult.getPlanFinishSegement();

		long start = scheme.getScheduleStart().getTime();
		int interval = scheme.getScheduleInterval();
		int needSegment = (int) Math.round(operationTask.getEstiTaskWork() / interval);
		if (needSegment == 0) {
			needSegment = 1;
		}

		operationTask.setPlanStartSegment(startSegment);
		operationTask.setPlanFinishSegment(endSegment);

		Date planStart = scheme.calDateFromSegement(operationTask.getPlanStartSegment());
		// 至这个时间段的终点,一定要加1,否则会造成误差,已经过充分演算
		// 减去这块造成的误差
		Date planFinish = scheme.calDateFromSegement(operationTask.getPlanFinishSegment() + 1);
		// 已经开始的任务不修改计划开始时间
		// if (operationTask.getActualStart() == null)
		operationTask.setPlanStart(planStart);

		operationTask.setPlanFinish(planFinish);
		if (log.isDebugEnabled()) {
			if (resource.getResUid().equals("D3"))
				log.debug("将任务:" + operationTask + "分派到资源:" + resource + "计划开始：" + startSegment + "计划结束：" + endSegment);
		}
		// 注意这句话要在分配主设备之前
		seizeResource(resource, operationTask, preAssignResult.getUseSegementList());

		// 找出调度中的主设备分配到工序任务上
		// SDevice device;
		// if (resource instanceof CombinedResource)
		// device = (SDevice) ((CombinedResource) resource).getMainResource();//
		// 取得主资源
		// else
		// device = (SDevice) resource;
		SDevice device = taskAssignScheme.getMainDevice();

		operationTask.setDevice(device);
		operationTask.setDeviceUid(device.getDeviceUid());
		// operationTask.setDeviceClass(device.getDeviceClass());
		// operationTask.setDeviceClassName(device.getDeviceClassName());
		if (log.isDebugEnabled()) {
			if (operationTask.getPlanFinish() == null || operationTask.getPlanStart() == null)
				log.debug("aaaaaaaaaaaaa");
		}

		device.addToQueue(operationTask);
		// if (device.getAssignedTaskQueue() != null)
		// device.getAssignedTaskQueue().add(operationTask);

		// 如果在观察日期之前
		// lqm todo
		// 这里必要性不大
		if (operationTask.getMaturity() != 1 && scheme.getWatchFinish() != null
				&& planStart.before(scheme.getWatchFinish())) {
			device.setNotRobustCount(device.getNotRobustCount() + 1);
		}

		// long setupEnd = (long) (startSegment * interval + operationTask
		// .getEstiPreTime());
		// TimeSection timeSection = new TimeSection();
		// timeSection.setStart(setupEnd);
		// timeSection.setEnd(endSegment * interval);
		// device.getOperTask().put(timeSection, operationTask);

		log.debug("assignTaskToResource 任务资源分配完成！");
		return true;
	}

	/**
	 * !
	 * 
	 * @param operTask
	 * @param device
	 * @param es
	 */
	// public boolean assignTaskToMultiCapacityDevice(
	// SOperationTask operationTask, Device device, int startSegment) {
	// long start = operationTask.getScheme().getScheduleStart().getTime();
	// int interval = operationTask.getScheme().getScheduleInterval();
	// int needSegment = (int) Math.round(operationTask.getEstiTaskWork()
	// / interval);
	// if (needSegment == 0) {
	// needSegment = 1;
	// }
	// int setupSegment = (int) Math.round(operationTask.getEstiPreTime()
	// / interval);
	// int endSegment = changeDeviceState(setupSegment, needSegment,
	// startSegment, device.getVirtualDeviceList().get(m));
	//
	// Date planStart = new Date((long) startSegment * interval * 60000
	// + start);
	// Date planFinish = new Date((long) endSegment * interval * 60000 + start);
	//
	// operationTask.setPlanStart(planStart);
	// operationTask.setPlanFinish(planFinish);
	// operationTask.setDevice(device);
	// operationTask.setDeviceUid(device.getDeviceUid());
	// operationTask.setDeviceClass(device.getDeviceClass());
	//
	// long setupEnd = (long) (startSegment * interval + operationTask
	// .getEstiPreTime());
	// TimeSection timeSection = new TimeSection();
	// timeSection.setStart(setupEnd);
	// timeSection.setEnd(endSegment * interval);
	// device.getOperTask().put(timeSection, operationTask);
	// return true;
	// }
	/**
	 * !
	 * 
	 * @param operTask
	 * @param device
	 * @return
	 */
	// public int[] preAssTaskForMultiCapacityDevice(SOperationTask
	// operationTask,
	// Device device) {
	//
	// List<Device> virtualDeviceList = device.getVirtualDeviceList();
	// int startSeg = preAssTask(operationTask, virtualDeviceList.get(0));
	// int index = 0;
	// for (int i = 1; i < virtualDeviceList.size(); i++) {
	// int temp = preAssTask(operationTask, virtualDeviceList.get(i));
	// if (temp < startSeg) {
	// startSeg = temp;
	// index = i;
	// }
	//
	// }
	// int[] flag = new int[2];
	// flag[0] = index;
	// flag[1] = startSeg;
	// return flag;
	// }
	// private int changeDeviceState(int setupSegment, int needSegment,
	// int startSegment, Resource resource) {
	// int processSegment = needSegment - setupSegment;
	//
	// int count = 0;
	// int index = startSegment;
	// int endSegment = startSegment;
	//
	// int segementCalendar;
	// int segementUse;
	//
	// ScheduleScheme scheduleSchema = resource.getScheme();
	//
	// if (setupSegment > 0) {
	// for (int i = startSegment; i < scheduleSchema.getTotalSegement(); i++) {
	// segementCalendar = resource.getSegementCalendar(i);
	// segementUse = resource.getSegementUse(i);
	// if (count == setupSegment) {
	// index = i;
	// count = 0;
	// break;
	// }
	// if ((segementCalendar == SDevice.DEVICE_NOMAL || segementCalendar ==
	// SDevice.DEVICE_OVERTIME)
	// && segementUse != SDevice.DEVICE_BREAKDOWN) {
	// resource.setSegementUse(i, Resource.RESOURCE_SETUP);
	//
	// count++;
	// }
	//
	// }
	// int flag = 0;
	// for (int i = index; i < scheduleSchema.getTotalSegement(); i++) {
	// segementCalendar = resource.getSegementCalendar(i);
	// segementUse = resource.getSegementUse(i);
	// if (count == processSegment) {
	// endSegment = i;
	// break;
	// }
	// if ((segementCalendar == SDevice.DEVICE_NOMAL || segementCalendar ==
	// SDevice.DEVICE_OVERTIME)
	// && segementUse != SDevice.DEVICE_BREAKDOWN) {
	// resource.setSegementUse(i, SDevice.DEVICE_PROCESS);
	// count++;
	// }
	//
	// }
	// } else {
	// for (int i = startSegment; i < scheduleSchema.getTotalSegement(); i++) {
	// segementCalendar = resource.getSegementCalendar(i);
	// segementUse = resource.getSegementUse(i);
	// if (count == needSegment) {
	// endSegment = i + 1;
	// break;
	// }
	// if ((segementCalendar == SDevice.DEVICE_NOMAL || segementCalendar ==
	// SDevice.DEVICE_OVERTIME)
	// && segementUse != SDevice.DEVICE_BREAKDOWN) {
	// resource.setSegementUse(i, SDevice.DEVICE_PROCESS);
	// count++;
	// }
	//
	// }
	// }
	// if (endSegment == startSegment) {
	// endSegment = startSegment + needSegment;
	// }
	// return endSegment;
	// }
	public void assignedSavedTask(SOperationTask operationTask, SDevice device) {

		// if (device.getResCapacity() == 1) {
		// seizeResource(device, operationTask);
		// } else {
		// int index = operationTask.getIndexForMultiCapacityDevice();
		// seizeResource(device.getVirtualDeviceList().get(index),
		// operationTask);
		// }
		seizeResource(device, operationTask, null);
		operationTask.setAssignState(SOperationTask.ASSNSTATE_SUCCESS);
	}

	// todo
	// 应该扣除运行，其它都是准备时间
	// 这样计算才更精确，因为有时是平行加工有最早完成时间的限制
	private void seizeResource(Resource resource, SOperationTask operationTask, List<Integer> useSegementList) {
		ScheduleScheme scheduleSchema = operationTask.getScheme();
		int segementCalendar;
		int segementUse;

		int interval = scheduleSchema.getScheduleInterval();

		int startSegment = scheduleSchema.calSegementFromDate(operationTask.getPlanStart());

		int finishSegment = scheduleSchema.calSegementFromDate(operationTask.getPlanFinish());

		if (startSegment < 0) {
			startSegment = 0;
		}

		int setupSegment;
		if (operationTask.getCompleteQty() != null && operationTask.getCompleteQty() > 0)
			setupSegment = 0;
		else
			setupSegment = (int) Math.round(operationTask.getEstiPreTime() / interval);

		int count = 0;
		// toDo
		// 预留设备上的不同工序的切换转移时间，应该是一个全局参数，现在缺省为30分钟
		int transferSegement = (int) Math.round(30 / scheduleSchema.getScheduleInterval());
		finishSegment += transferSegement;
		if (finishSegment > scheduleSchema.getTotalSegement() - 1) {
			finishSegment = scheduleSchema.getTotalSegement() - 1;
		}
		if (useSegementList != null) {
			for (int i = 0; i < useSegementList.size(); i++) {
				int segement = useSegementList.get(i);
				if (count < setupSegment) {
					resource.setSegementUse(segement, Resource.RESOURCE_SETUP, operationTask);
					count++;
				} else {
					resource.setSegementUse(segement, Resource.RESOURCE_PROCESS, operationTask);
				}

			}
			operationTask.setUseSegementList(useSegementList);
		} else {

			for (int i = startSegment; i < finishSegment; i++) {

				segementCalendar = this.scheduledeviceManager.getSegementCalendar(resource, i);
				segementUse = resource.getSegementUse(i);
				if ((segementCalendar == SDevice.DEVICE_NOMAL || segementCalendar == SDevice.DEVICE_OVERTIME)
						&& segementUse == Resource.RESOURCE_IDLE) {
					if (count < setupSegment) {
						resource.setSegementUse(i, Resource.RESOURCE_SETUP, operationTask);
						operationTask.getUseSegementList().add(i);
						count++;
					} else {
						resource.setSegementUse(i, Resource.RESOURCE_PROCESS, operationTask);
						operationTask.getUseSegementList().add(i);
					}
				}
			}
		}

		// long setupEnd = (long) (startSegment * interval + operationTask
		// .getEstiPreTime());
		// TimeSection timeSection = new TimeSection();
		// timeSection.setStart(setupEnd);
		// timeSection.setEnd(finishSegment * interval);
		// resource.getOperTask().put(timeSection, operationTask);
	}

	public ReadyTaskManager getReadyTaskManager() {
		return readyTaskManager;
	}

	public void setReadyTaskManager(ReadyTaskManager readyTaskManager) {
		this.readyTaskManager = readyTaskManager;
	}

	public ScheduleLinkManager getScheduleLinkManager() {
		return scheduleLinkManager;
	}

	public void setScheduleLinkManager(ScheduleLinkManager scheduleLinkManager) {
		this.scheduleLinkManager = scheduleLinkManager;
	}

	public void preAssnTaskCallBack(TaskAssignScheme alterResource) {
		// TODO Auto-generated method stub

	}

	/*
	 * lock状态下开始结束设备都不需要设置 锁定设备占用资源还是与非锁定任务不一样 这里对 多工作台设备还是未处理好
	 */
	/**
	 * lqm todo 没有增加对锁定工作台任务的处理 对多工作台设备只占用了主设备
	 */
	public void assignLockTask(SOperationTask operationTask) {

		// if (device.getResCapacity() == 1) {
		// seizeResource(device, operationTask);
		// } else {
		// int index = operationTask.getIndexForMultiCapacityDevice();
		// seizeResource(device.getVirtualDeviceList().get(index),
		// operationTask);
		// }
		ScheduleScheme scheduleSchema = operationTask.getScheme();
		int segementCalendar;
		int segementUse;

		int interval = scheduleSchema.getScheduleInterval();

		int startSegment = scheduleSchema.calSegementFromDate(operationTask.getPlanStart());

		int finishSegment = scheduleSchema.calSegementFromDate(operationTask.getPlanFinish());

		if (startSegment < 0) {
			startSegment = 0;
		}
		if (finishSegment > scheduleSchema.getTotalSegement() - 1) {
			finishSegment = scheduleSchema.getTotalSegement() - 1;
		}

		operationTask.setPlanStartSegment(startSegment);
		operationTask.setPlanFinishSegment(finishSegment);

		// toDo
		// 预留设备上的不同工序的切换转移时间，应该是一个全局参数，现在缺省为30分钟
		int transferSegement = (int) Math.round(30 / scheduleSchema.getScheduleInterval());

		finishSegment += transferSegement;
		if (finishSegment > scheduleSchema.getTotalSegement() - 1) {
			finishSegment = scheduleSchema.getTotalSegement() - 1;
		}

		int setupSegment;
		// todo
		// 对改派设备后重新开始准备没做好
		if (operationTask.getCompleteQty() > 0)
			setupSegment = 0;
		else
			setupSegment = (int) Math.round(operationTask.getEstiPreTime() / interval);

		int needSegment = (int) Math.round(operationTask.getEstiTaskWork() / interval);
		if (needSegment == 0) {
			needSegment = 1;
		}

		int count = 0;

		SDevice device = operationTask.getDevice();

		if (device == null) {
			operationTask.setDevice(scheduleSchema.getVirtualCoDevice());
			operationTask.setDeviceUid(scheduleSchema.getVirtualCoDevice().getDeviceUid());
			device = operationTask.getDevice();
		}
		device.addToQueue(operationTask);

		// if (device.getAssignedTaskQueue() != null)
		// device.getAssignedTaskQueue().add(operationTask);

		operationTask.setAssignedResource(device);

		for (int i = startSegment; i < finishSegment; i++) {

			segementCalendar = this.scheduledeviceManager.getSegementCalendar(device, i);
			segementUse = device.getSegementUse(i);
			if ((segementCalendar == SDevice.DEVICE_NOMAL || segementCalendar == SDevice.DEVICE_OVERTIME)
					&& segementUse == Resource.RESOURCE_IDLE) {
				if (count < setupSegment) {
					device.setSegementUse(i, Resource.RESOURCE_SETUP, operationTask);
					operationTask.getUseSegementList().add(i);

				} else {
					device.setSegementUse(i, Resource.RESOURCE_PROCESS, operationTask);
					operationTask.getUseSegementList().add(i);
				}
				count++;
				// 锁定任务在这一段时间内自由占用资源
				// if (count > needSegment)
				// break;
			}

		}

		operationTask.setAssignState(SOperationTask.ASSNSTATE_SUCCESS);
	}

	/**
	 * 分派在资源视图中已经调整的任务 by hba
	 * 
	 * @param operationTask
	 */
	private void assignDispatchedTask(SOperationTask operationTask) {

		ScheduleScheme scheduleSchema = operationTask.getScheme();
		int segementCalendar;
		int segementUse;

		int interval = scheduleSchema.getScheduleInterval();

		int startSegment = scheduleSchema.calSegementFromDate(operationTask.getPlanStart());

		int finishSegment = scheduleSchema.calSegementFromDate(operationTask.getPlanFinish());

		if (startSegment < 0) {
			startSegment = 0;
		}
		if (finishSegment > scheduleSchema.getTotalSegement() - 1) {
			finishSegment = scheduleSchema.getTotalSegement() - 1;
		}

		operationTask.setPlanStartSegment(startSegment);
		operationTask.setPlanFinishSegment(finishSegment);

		// toDo
		// 预留设备上的不同工序的切换转移时间，应该是一个全局参数，现在缺省为30分钟
		int transferSegement = (int) Math.round(30 / scheduleSchema.getScheduleInterval());

		finishSegment += transferSegement;
		if (finishSegment > scheduleSchema.getTotalSegement() - 1) {
			finishSegment = scheduleSchema.getTotalSegement() - 1;
		}

		int setupSegment;
		// todo
		// 对改派设备后重新开始准备没做好
		if (operationTask.getCompleteQty() > 0)
			setupSegment = 0;
		else
			setupSegment = (int) Math.round(operationTask.getEstiPreTime() / interval);

		int needSegment = (int) Math.round(operationTask.getEstiTaskWork() / interval);
		if (needSegment == 0) {
			needSegment = 1;
		}

		int count = 0;

		SDevice device = operationTask.getDevice();
		// 如果设备为空，则需要计算该工序的可选设备列表，进行投标(投标规则要修改)hba
		/**
		 * 1、
		 */
		if (device == null) {
			operationTask.setDevice(scheduleSchema.getVirtualCoDevice());
			operationTask.setDeviceUid(scheduleSchema.getVirtualCoDevice().getDeviceUid());
			device = operationTask.getDevice();
		}
		device.addToQueue(operationTask);

		// if (device.getAssignedTaskQueue() != null)
		// device.getAssignedTaskQueue().add(operationTask);

		operationTask.setAssignedResource(device);

		for (int i = startSegment; i < finishSegment; i++) {

			segementCalendar = this.scheduledeviceManager.getSegementCalendar(device, i);
			segementUse = device.getSegementUse(i);
			if ((segementCalendar == SDevice.DEVICE_NOMAL || segementCalendar == SDevice.DEVICE_OVERTIME)
					&& segementUse == Resource.RESOURCE_IDLE) {
				if (count < setupSegment) {
					device.setSegementUse(i, Resource.RESOURCE_SETUP, operationTask);
					operationTask.getUseSegementList().add(i);

				} else {
					device.setSegementUse(i, Resource.RESOURCE_PROCESS, operationTask);
					operationTask.getUseSegementList().add(i);
				}
				count++;
				// 锁定任务在这一段时间内自由占用资源
				// if (count > needSegment)
				// break;
			}

		}

		operationTask.setAssignState(SOperationTask.ASSNSTATE_SUCCESS);
	}

	/**
	 * 分派前处理
	 * 
	 * @see com.mes.schedule.manager.impl.AssignManager#doAssignTask(com.mes.schedule.persistence.domain.SOperationTask)
	 */

	public PreAssignResult doAssignTask(SOperationTask operationTask) throws Exception {
		PreAssignResult assignResult = null;
		operationTask.setAssignState(SOperationTask.ASSNSTATE_FAILURE);

		if (log.isDebugEnabled()) {
			if (operationTask.getTaskUid().equals("9cf3469e-883e-4798-873f-2812bbba2d35")) {
				log.debug(operationTask);
			}
			if ("p229".equals(operationTask.getDrawingId()))
				log.debug(operationTask);
		}

		// 设置调度顺序
		ScheduleScheme scheme = operationTask.getScheme();
		// int totalAssignCount = scheme.getTotalAssignCount() + 1;
		// operationTask.setScheduleOrder(totalAssignCount);
		// if (log.isDebugEnabled()) {
		// if (operationTask.getNotes() == null)
		// operationTask.setNotes(String.valueOf(i));
		// else
		// operationTask.setNotes(operationTask.getNotes() + "," + i);
		// }
		scheme.addOneAssignCount();
		operationTask.setScheduleOrder(scheme.getTotalAssignCount());
		// 设置该任务的调度次数
		operationTask.setScheduleCount(operationTask.getScheduleCount() + 1);

		// 由于中间任务取消跌代的关系，将计算最早开始时间放在了afterassign之后
		// 单由于首工序没有前置任务，导致其无法计算开始时间
		// 从而导致用户自己设置的earlystart无法发挥作用
		// if (operationTask.getPredLinkSet().size() == 0) {
		// scheduleOperationTaskManager.calcControlEarlyStart(operationTask);
		// }
		// 手动排产结果的处理 by hba(暂时使得手动调整的结果优先于锁定)
		if (operationTask.getManualScheduleState() != null
				&& operationTask.getManualScheduleState() >= SOperationTask.MANUAL_SCHEDULED) {
			// 以下是正式分配手动派工任务
			log.debug("开始正式分派已手动调整任务:" + operationTask);
			this.assignDispatchedTask(operationTask);
		}

		else if (operationTask.getCalLocked() != null && operationTask.getCalLocked().equals(1)) {
			// 以下是正式分配锁定任务
			log.debug("开始正式分派锁定任务:" + operationTask);
			this.assignLockTask(operationTask);
		} else {

			// 以下是正式分配例程
			log.debug("开始正式分派任务:" + operationTask);
			// 加在就绪任务之前
			scheduleOperationTaskManager.calcControlEarlyStart(operationTask);
			scheduleOperationTaskManager.calcControlEarlyFinish(operationTask);

			// 增加对钳工并行设备的处理
			// if(operationTask.getAlterResourceMap().values().iterator().next())
			//
			//
			// List<TaskAssignScheme> alterResourceList =
			// getAlterResourceList(operationTask);

			// 分派到设备
			TaskAssignScheme selectedTaskAssignScheme = tenderTask(operationTask);

			if (selectedTaskAssignScheme != null) {
				assignTaskToResource(operationTask, selectedTaskAssignScheme);
				operationTask.setAssignState(SOperationTask.ASSNSTATE_SUCCESS);
				assignResult = selectedTaskAssignScheme.getPreAssignResult();
			}
		}

		// lqm 对锁定任务的返回没有处理好

		return assignResult;

	}

	private boolean canParallel(SOperationTask operationTask) {
		// this.scheduleOperationTaskManager
		// for(ResourceConstraint
		// ResourceConstraint:operationTask.getAlterResourceMap().values())
		// {
		//
		// .iterator().next()
		//
		// }
		return false;
	}

	/**
	 * 
	 * 取消工序任务并将其重新加入就绪任务集合
	 * 
	 * 
	 */

	public void moveRight(SOperationTask operationTask) throws Exception {
		// try {
		// ScheduleScheme scheme = operationTask.getScheme();
		//
		// // TODO Auto-generated method stub
		// // 锁定任务 直接退出
		// // 已完成任务 直接退出
		// // 已开始任务由于最先已经调度，所以不允许取消
		// // 未调度成功任务直接退出
		//
		// // 2014-5-9, 允许失败的任务取消
		// if (operationTask.getLocked().equals(1)
		// || operationTask.isFinished() || operationTask.isStarted()) {
		// return;
		// }
		// if (!(operationTask.getAssignState()
		// .equals(SOperationTask.ASSNSTATE_SUCCESS))) {
		// // if (scheme.getReadyTaskS().contains(operationTask)) {
		// // // 取消任务时后续任务已经在调度集合中，一定要将其清除出去
		// // this.removeFromReadyTasks(operationTask);
		// // }
		// return;
		// }
		//
		// log.debug("开始取消分派：" + operationTask.toFriendlyString() + ",次数:"
		// + operationTask.getScheduleCount());
		// if (log.isDebugEnabled()) {
		//
		// if (operationTask.getDevice() instanceof UcDevice) {
		// log.isDebugEnabled();
		// }
		//
		// if (operationTask.getTaskUid().equals(
		// "05dd29d5-6ce0-43cd-9b30-c422e48c89a8")
		//
		// ) {
		// log.debug(operationTask);
		// }
		// }
		//
		// if (log.isDebugEnabled()) {
		// scheme.addOneCancelAssignCount();
		// }
		// operationTask.setScheduleOrder(0);
		//
		// operationTask.setAssignState(SOperationTask.ASSNSTATE_WAITING);
		//
		// // 一定要将其从设备的已分派任务队列中清除
		// if (operationTask.getDevice() != null) {
		// operationTask.getDevice().getAssignedTaskQueue().remove(
		// operationTask);
		// }
		//
		// // 取消其在设备上的占用
		// // 锁定任务处理和设备队列处理
		// // 只要未锁定则将其时间设置为空
		// operationTask.setPlanStart(null);
		// operationTask.setPlanFinish(null);
		// // lqm ，这个对主设备没限制主
		// // 多线程todo
		// synchronized (operationTask.getAssignedResource()) {
		// // 注意不是设备，可能是组合资源
		// // 将设备设置为闲置状态
		// Resource resource = operationTask.getAssignedResource();
		// if (resource != null) {
		// // 占用时间段
		// for (Integer seq : operationTask.getUseSegementList()) {
		// resource.setSegementUse(seq, Resource.RESOURCE_IDLE,
		// null);
		// }
		//
		// operationTask.setAssignedResource(null);
		// }
		// }
		// operationTask.getUseSegementList().clear();
		//
		// if (this.scheduleOperationTaskManager
		// .canChangeDevice(operationTask)) {
		// operationTask.setDeviceUid(null);
		// operationTask.setDevice(null);
		// }
		//
		// // 后续任务在调度中一定将其先取消
		// for (SOperationLink succLink : operationTask.getSuccLinkSet()) {
		// SOperationTask so = succLink.getSuccOperationTask();
		// if (so.getGroupTask() != null)
		// so = so.getGroupTask();
		// if (scheme.getReadyTaskS().contains(so)) {
		// // 取消任务时后续任务已经在调度集合中，一定要将其清除出去
		// this.removeFromReadyTasks(so);
		// }
		// }
		//
		// // 将其后续任务也设置为取消调度
		// // 2014-04-23 后续任务全部取消调度没有必要
		// // if (cascadeSucc) {
		// // for (SOperationLink succLink : operationTask.getSuccLinkSet()) {
		// // SOperationTask so = succLink.getSuccOperationTask();
		// // if (so.getGroupTask() != null)
		// // so = so.getGroupTask();
		// //
		// // this.cancelAssignTask(so, cascadeSucc);
		// // }
		// // }
		//
		// } catch (RuntimeException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// throw e;
		// }

	}

	/**
	 * 
	 * 取消工序任务并将其重新加入就绪任务集合
	 * 
	 * 
	 */

	public void cancelAssignTask(SOperationTask operationTask, boolean cascadeSucc) throws Exception {

		try {
			ScheduleScheme scheme = operationTask.getScheme();

			// TODO Auto-generated method stub
			// 锁定任务 直接退出
			// 已完成任务 直接退出
			// 已开始任务由于最先已经调度，所以不允许取消
			// 未调度成功任务直接退出

			// 2014-5-9, 允许失败的任务取消
			if (operationTask.getCalLocked().equals(1) || operationTask.isFinished() || operationTask.isStarted()) {
				return;
			}
			if (!(operationTask.getAssignState().equals(SOperationTask.ASSNSTATE_SUCCESS))) {
				return;
			}

			log.info("开始取消分派：" + operationTask.toFriendlyString() + ",次数:" + operationTask.getScheduleCount());
			if (operationTask.getDeviceUid().equals("D3"))
				log.info(operationTask + ",earlyStart:"
						+ operationTask.getScheme().calSegementFromDate(operationTask.getControlEarlyStart())
						+ ",remainwork:" + operationTask.getRemainWork() + ",estiwork:"
						+ operationTask.getEstiTaskWork());

			if (log.isDebugEnabled()) {

				if (operationTask.getDevice() instanceof UcDevice) {
					log.isDebugEnabled();
				}

				if (operationTask.getTaskUid().equals("ad7606a7-4dcf-4dc1-901f-e71d262b0591")

				) {
					log.debug(operationTask);
				}
			}

			if (log.isDebugEnabled()) {
				scheme.addOneCancelAssignCount();
			}
			operationTask.setScheduleOrder(0);

			operationTask.setAssignState(SOperationTask.ASSNSTATE_WAITING);

			// 一定要将其从设备的已分派任务队列中清除,在设置planstart之前
			if (operationTask.getDevice() != null) {
				operationTask.getDevice().getAssignedTaskQueue().remove(operationTask);
			}

			// 取消其在设备上的占用
			// 锁定任务处理和设备队列处理
			// 只要未锁定则将其时间设置为空
			operationTask.setPlanStart(null);
			operationTask.setPlanFinish(null);
			if (log.isDebugEnabled()) {
				if (operationTask.getAssignedResource() == null) {
					log.debug("1");
				}
			}

			// lqm ，这个对主设备没限制主
			// 多线程todo
			if (operationTask.getAssignedResource() != null) {
				synchronized (operationTask.getAssignedResource()) {
					// 注意不是设备，可能是组合资源
					// 将设备设置为闲置状态
					Resource resource = operationTask.getAssignedResource();
					if (resource != null) {
						// 占用时间段
						for (Integer seq : operationTask.getUseSegementList()) {
							resource.setSegementUse(seq, Resource.RESOURCE_IDLE, operationTask);
						}

						operationTask.setAssignedResource(null);
					}
				}
			}
			if (operationTask.getUseSegementList() != null)
				operationTask.getUseSegementList().clear();

			if (this.scheduleOperationTaskManager.canChangeDevice(operationTask)) {
				operationTask.setDeviceUid(null);
				operationTask.setDevice(null);
			}

			// 后续任务在调度中一定将其先取消
			for (SOperationLink succLink : operationTask.getSuccLinkSet()) {
				SOperationTask so = succLink.getSuccOperationTask();
				if (so.getGroupTask() != null)
					so = so.getGroupTask();
				this.removeFromReadyTasks(so);

			}

			// 将其后续任务也设置为取消调度
			// 2014-04-23 后续任务全部取消调度没有必要
			if (cascadeSucc) {
				for (SOperationLink succLink : operationTask.getSuccLinkSet()) {
					SOperationTask so = succLink.getSuccOperationTask();
					if (so.getGroupTask() != null)
						so = so.getGroupTask();

					this.cancelAssignTask(so, cascadeSucc);
				}
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw e;
		}

	}

	// 动态计算设备由于序列而产生的最早开始时间段,
	protected int getDeviceEarlyStartSegement(SDevice device, SOperationTask scheduleOperationTask) {

		if (device.getDeviceUid().equals("3401017")) {
			log.debug(device);
		}

		// 重新计算设备上由于设备序列允许的最早开始时间
		TreeSet<SOperationTask> interruptDeviceQueue = device.getInterruptDeviceQueue();
		int startSegment = 0;
		int endSegement = 0;

		if (interruptDeviceQueue != null && interruptDeviceQueue.size() > 0) {

			try {

				double queueLength = 0;
				// 累加没有调度成功的任务的工时
				// 注意有这种序列 1，1，2,2,3,3
				// int lastSuccessSeq=0;
				for (SOperationTask queueTask : interruptDeviceQueue.descendingSet()) {
					// by lqm
					// 防止那种变态的设置，后置任务与前置任务均在同一台设备，但后置任务设置了设备序列
					if (scheduleOperationTask != null
							&& (this.scheduleLinkManager.isPredTask(scheduleOperationTask, queueTask)))
						continue;
					if (queueTask.getAssignState().equals(SOperationTask.ASSNSTATE_SUCCESS)) {
						if (queueTask.getPlanFinishSegment() > startSegment)
							startSegment = queueTask.getPlanFinishSegment();
						// break;
					} else {

						queueLength += queueTask.getEstiTaskWork();
					}

				}

				endSegement = this.scheduledeviceManager.calFinishSegement(device, startSegment, queueLength);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		return endSegement;

	}

	// // 动态计算设备的最早开始时间段
	// protected void refreshDeviceEarlyStartSegement(SDevice device) {
	//
	// if (device.getDeviceUid().equals("192168100147")) {
	// log.debug(device);
	// }
	//
	// // 重新计算设备上由于设备序列允许的最早开始时间
	// TreeSet<SOperationTask> interruptDeviceQueue = device
	// .getInterruptDeviceQueue();
	// int startSegment = 0;
	// int endSegement = 0;
	//
	// if (interruptDeviceQueue != null && interruptDeviceQueue.size() > 0) {
	//
	// double queueLength = 0;
	// // 累加没有调度成功的任务的工时
	// // 注意有这种序列 1，1，2,2,3,3
	// for (SOperationTask queueTask : interruptDeviceQueue
	// .descendingSet()) {
	// if (queueTask.getAssignState().equals(
	// SOperationTask.ASSNSTATE_SUCCESS)) {
	// startSegment = queueTask.getPlanFinishSegment();
	// break;
	// } else {
	// queueLength += queueTask.getEstiTaskWork();
	// }
	//
	// }
	//
	// endSegement = this.deviceManager.calFinishSegement(device,
	// startSegment, queueLength);
	//
	// }
	// device.setDeviceSeqEarlyStartSegement(endSegement);
	//
	// }
	/**
	 * 找到某一个时段对应的任务
	 */
	protected SOperationTask getSegementTask(TaskAssignScheme taskAssignScheme, int i)

	{
		SDevice mainDevice = taskAssignScheme.getMainDevice();
		Resource resource = taskAssignScheme.getResource();
		SOperationTask segmenTask = null;
		// 多能力设备的例外处理
		if (mainDevice instanceof McDevice)
			segmenTask = resource.getSegementTask(i);
		else
			segmenTask = mainDevice.getSegementTask(i);
		return segmenTask;
	}

	/**
	 * 
	 * @param taskAssignScheme
	 * @param i
	 */
	protected void satisfyNeedSegmentPro(TaskAssignScheme taskAssignScheme, PreAssignResult result, int startSegment,
			int currentSegment, int needSegment, int freeSegment)

	{
		// 完成时间一定

		result.setPlanFinishSegement(currentSegment);
		// 处理平顺平行时的最早完成时间限制
		if (freeSegment <= needSegment) {
			result.setPlanStartSegement(startSegment);
		} else {
			Integer mustStartSegment = taskAssignScheme.getOperationTask().getCalMustStartSegment();
			if (mustStartSegment != null && startSegment >= mustStartSegment)
				result.setPlanStartSegement(startSegment);
			else {

				// result.getUseSegementList().clear();
				// 重换起点时会自动取消掉之前记录的任务
				result.getNeedCancelAssignTasks().clear();
				// lqm todo
				// 中断数量暂时无用
				// 建议不加以考虑
				// result.setInterruptCount(0);
				int newfreeSegment = 0;

				Integer[] aList = result.getUseSegementList().toArray(new Integer[0]);
				result.getUseSegementList().clear();
				for (int ri = aList.length - 1; ri >= 0; ri--) {
					newfreeSegment++;
					int s = aList[ri];
					if (newfreeSegment <= needSegment) {
						result.getUseSegementList().add(s);
						SOperationTask segmenTask = getSegementTask(taskAssignScheme, s);
						if (segmenTask != null)
							result.getNeedCancelAssignTasks().add(segmenTask);
						if (newfreeSegment == needSegment || ri == 0) {
							result.setPlanStartSegement(s);
							break;
						}
					}
				}
			}
		}

		result.setAssnSuccess(true);

	}

}
